// scraper/supabase-scraper.js
const axios = require('axios');
const { createClient } = require('@supabase/supabase-js');
require('dotenv').config();

// === 1. 初始化 Supabase 客户端 ===
const supabase = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_ANON_KEY);

// === 2. 高德API配置 ===
const AMAP_BASE_URL = 'https://restapi.amap.com/v3/place/around';
const KEYWORD = '充电桩';
const RADIUS = 5000; // 5km
const OFFSET = 20;
const MAX_PAGES = 5; // 避免超限

// === 3. 南京市网格中心点 ===
const NANJING_GRID_CENTERS = [
    { lng: 118.7969, lat: 32.0603 }, // 市中心
    { lng: 118.8500, lat: 32.0500 }, // 东
    { lng: 118.7500, lat: 32.0500 }, // 西
    { lng: 118.7969, lat: 32.1000 }, // 北
    { lng: 118.7969, lat: 31.9800 }, // 南
];

// === 4. 解析运营商和类型 ===
const parseOperator = (name) => {
    if (name.includes('特来电')) return '特来电';
    if (name.includes('星星充电')) return '星星充电';
    if (name.includes('国家电网') || name.includes('e充电')) return '国家电网';
    if (name.includes('云快充')) return '云快充';
    if (name.includes('蔚来') || name.includes('NIO')) return '蔚来能源';
    if (name.includes('小桔')) return '小桔充电';
    if (name.includes('开迈斯') || name.includes('CAMS')) return '开迈斯';
    return '其他';
};

const parseChargerType = (name, address) => {
    if (name.includes('快充') || address.includes('快充')) return 'DC';
    if (name.includes('慢充') || address.includes('慢充')) return 'AC';
    return 'AC+DC';
};

// === 5. 主抓取函数 ===
const fetchChargingStations = async (center) => {
    const { lng, lat } = center;
    let allStations = [];
    let page = 1;
    let hasMore = true;

    console.log(`🔍 开始抓取中心点 (${lng}, ${lat}) 的数据...`);

    while (hasMore && page <= MAX_PAGES) {
        try {
            const response = await axios.get(AMAP_BASE_URL, {
                params: {
                    key: process.env.AMAP_WEB_SERVICE_KEY,
                    keywords: KEYWORD,
                    location: `${lng},${lat}`,
                    radius: RADIUS,
                    offset: OFFSET,
                    page: page,
                    extensions: 'base'
                },
                timeout: 10000
            });

            const data = response.data;

            if (data.status === '1' && data.count > 0) {
                const pois = data.pois;
                console.log(`  📄 第 ${page} 页，获取 ${pois.length} 条数据`);
                allStations.push(...pois);

                if (pois.length < OFFSET) {
                    hasMore = false;
                }
            } else {
                console.log(`  ⚠️  第 ${page} 页无数据或请求失败:`, data.info || data.status);
                hasMore = false;
            }

            page++;
            await new Promise(resolve => setTimeout(resolve, parseInt(process.env.REQUEST_INTERVAL)));

        } catch (error) {
            if (error.response) {
                console.error(`❌ API 请求失败 (状态码 ${error.response.status}):`, error.response.data);
            } else if (error.code === 'ECONNABORTED') {
                console.error('❌ 请求超时');
            } else {
                console.error('❌ 未知错误:', error.message);
            }
            hasMore = false;
        }
    }

    return allStations;
};

// === 6. 数据处理与保存到 Supabase ===
// 在 processAndSaveData 函数中，替换 upsert 逻辑
/**
 * 处理原始数据并保存到 Supabase
 * 使用 RPC 调用自定义函数来安全插入地理空间数据
 */
/**
 * 处理原始数据并保存到 Supabase (批量 RPC 优化版)
 */
/**
 * 处理原始数据并保存到 Supabase (批量 RPC 优化版)
 */
const processAndSaveData = async (rawData) => {
    console.log(`🔍 原始数据条数: ${rawData.length}`);

    // 1. 去重 (基于高德ID)
    const uniqueMap = new Map();
    rawData.forEach(item => {
        if (!uniqueMap.has(item.id)) {
            uniqueMap.set(item.id, item);
        }
    });
    const uniqueData = Array.from(uniqueMap.values());
    console.log(`✅ 去重后，共 ${uniqueData.length} 个唯一充电站`);

    // 2. 转换并验证数据
    const stationsToProcess = []; // ✅ 这里定义了 stationsToProcess
    let invalidCount = 0;

    for (const item of uniqueData) {
        try {
            const locStr = (item.location || '').trim();
            if (!locStr) {
                console.warn(`⚠️ 位置为空，跳过: ${item.id}`);
                invalidCount++;
                continue;
            }

            const coords = locStr.split(',').map(s => s.trim());
            if (coords.length !== 2) {
                console.warn(`⚠️ 位置格式错误，跳过: ${item.id}, ${locStr}`);
                invalidCount++;
                continue;
            }

            const lng = parseFloat(coords[0]);
            const lat = parseFloat(coords[1]);

            if (isNaN(lng) || isNaN(lat) || lng < -180 || lng > 180 || lat < -90 || lat > 90) {
                console.warn(`⚠️ 经纬度无效，跳过: ${item.id}, [${lng}, ${lat}]`);
                invalidCount++;
                continue;
            }

            // ✅ 收集用于 RPC 调用的数据
            stationsToProcess.push({
                amap_id: item.id,
                name: item.name,
                address: item.address,
                tel: item.tel || null,
                province: item.pname,
                city: item.cityname,
                district: item.adname,
                business_area: item.business_area || null,
                operator: parseOperator(item.name),
                charger_type: parseChargerType(item.name, item.address),
                coordinates: [lng, lat] // 存储坐标
            });

        } catch (err) {
            console.error(`❌ 处理数据项失败 (${item.id}):`, err.message);
            invalidCount++;
        }
    }

    if (invalidCount > 0) {
        console.log(`⚠️  跳过 ${invalidCount} 条无效数据`);
    }

    if (stationsToProcess.length === 0) {
        console.log('❌ 无有效数据可插入');
        return;
    }

    console.log(`📌 准备通过 RPC 批量插入/更新 ${stationsToProcess.length} 条数据`);

    // 3. 批量调用 RPC 函数
    const BATCH_SIZE = 50; // 每批 50 条
    let totalSuccess = 0;
    let totalError = 0;
    let allErrors = [];

    // 将数据分批处理
    for (let i = 0; i < stationsToProcess.length; i += BATCH_SIZE) {
        const batch = stationsToProcess.slice(i, i + BATCH_SIZE);

        // ✅ 构建符合批量函数参数要求的数组
        const batchForRpc = batch.map(station => ({
            p_amap_id: station.amap_id,
            p_name: station.name,
            p_address: station.address,
            p_tel: station.tel,
            p_province: station.province,
            p_city: station.city,
            p_district: station.district,
            p_business_area: station.business_area,
            p_operator: station.operator,
            p_charger_type: station.charger_type,
            p_geojson: {
                type: 'Point',
                coordinates: station.coordinates // [lng, lat]
            }
        }));

        try {
            // ✅ 调用批量 RPC 函数
            const { data, error } = await supabase.rpc('insert_charging_stations_batch', {
                p_stations: batchForRpc
            });

            if (error) {
                throw error;
            }

            // 累加结果
            totalSuccess += data.success_count;
            totalError += data.error_count;

            if (data.error_list && data.error_list.length > 0) {
                allErrors.push(...data.error_list);
            }

            console.log(`✅ 第 ${Math.floor(i / BATCH_SIZE) + 1} 批 (${batch.length} 条) 处理完成: 成功 ${data.success_count}, 失败 ${data.error_count}`);

        } catch (err) {
            console.error(`❌ 批量 RPC 调用失败 (批次 ${Math.floor(i / BATCH_SIZE) + 1}):`, err.message);
            // 如果整个批次失败，记录错误数量
            totalError += batch.length;
            // 可选：将批次中所有 ID 记录为错误
            batch.forEach(station => {
                allErrors.push({
                    amap_id: station.amap_id,
                    error: `Batch call failed: ${err.message}`
                });
            });
        }
    }

    console.log(`✅ 批量处理完成: 总成功 ${totalSuccess}, 总失败 ${totalError}`);

    if (allErrors.length > 0) {
        console.log('📋 详细错误:');
        allErrors.slice(0, 10).forEach(err => { // 只打印前10条
            console.log(`  - ${err.amap_id}: ${err.error}`);
        });
        if (allErrors.length > 10) {
            console.log(`  ... 还有 ${allErrors.length - 10} 条错误`);
        }
    }

    if (totalError > 0) {
        console.warn(`⚠️  共有 ${totalError} 条记录插入失败`);
        // 根据需要决定是否抛出错误
        // throw new Error(`${totalError} 条记录插入失败`);
    }
};
// === 7. 主函数 ===
const main = async () => {
    console.log('🚀 开始抓取南京市充电桩数据 (Supabase版)...');

    let allRawData = [];

    // 1. 遍历网格抓取数据
    for (const center of NANJING_GRID_CENTERS) {
        try {
            const stations = await fetchChargingStations(center);
            allRawData.push(...stations);
        } catch (error) {
            console.error(`❌ 抓取中心点失败:`, error.message);
        }
    }

    console.log(`🔍 所有中心点抓取完成，共获取原始数据 ${allRawData.length} 条`);

    if (allRawData.length === 0) {
        console.error('❌ 未获取到任何数据');
        return;
    }

    // 2. 处理并保存到 Supabase
    try {
        await processAndSaveData(allRawData);
    } catch (error) {
        console.error('❌ 数据处理或保存失败:', error);
    }

    console.log('👋 抓取任务结束');
};

// === 8. 执行 ===
main().catch(err => {
    console.error('❌ 程序执行出错:', err);
    process.exit(1);
});